#include <xen/config.h>
#include <hypervisor-ifs/hypervisor-if.h>
#include <asm/page.h>
+#include <asm/msr.h>
#define SECONDARY_CPU_FLAG 0xA5A5A5A5
- .text
+ .text
.code32
ENTRY(start)
.org 0x004
/*** MULTIBOOT HEADER ****/
/* Magic number indicating a Multiboot header. */
- .long 0x1BADB002
- /* Flags to bootloader (see Multiboot spec). */
- .long 0x00000002
- /* Checksum: must be the negated sum of the first two fields. */
- .long -0x1BADB004
+ .long 0x1BADB002
+ /* Flags to bootloader (see Multiboot spec). */
+ .long 0x00000002
+ /* Checksum: must be the negated sum of the first two fields. */
+ .long -0x1BADB004
.org 0x010
.asciz "Bad CPU: does not support 64-bit (long) mode."
mov $0x20,%ecx # X86_CR4_PAE
mov %ecx,%cr4
- cmp $(SECONDARY_CPU_FLAG),%ebx
- je start_paging
-
mov %ebx,0x1001e0 /* Multiboot info struct */
mov %eax,0x1001e4 /* Multiboot magic value */
- /* Initialize mappings of 1GB of memory. */
- mov $0x103000,%edi /* idle_pg_table_l2 */
- mov $0x1e3,%eax /* PRESENT+RW+A+D+PSE+GLOBAL */
- mov $512,%ecx
-1: stosl
- add $0x200000,%eax
- loop 1b
-
-start_paging:
+ /* Load pagetable base register. */
mov $0x101000,%eax /* idle_pg_table */
mov %eax,%cr3
+
+ /* Set up EFER (Extended Feature Enable Register). */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ /* Long Mode, SYSCALL/SYSRET, No-Execute */
+ movl $(EFER_LME|EFER_SCE|EFER_NX),%eax
+ wrmsr
+
mov $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
mov %eax,%cr0
jmp 1f
-1: /* Now in compatibility mode. Long-jump into 64-bit mode. */
- ljmp $(__HYPERVISOR_CS64),$0x1000e0
+1: /* Now in compatibility mode. Long-jump into 64-bit mode. */
+ ljmp $(__HYPERVISOR_CS64),$0x100100
+
.code64
- .org 0x00e0
+ .org 0x0100
- /* Jump to high mappings. */
- mov high_start(%rip),%rax
- push %rax
- ret
-__high_start:
-
/* Install relocated selectors (FS/GS unused). */
lgdt gdt_descr(%rip)
mov $(__HYPERVISOR_DS),%ecx
mov stack_start(%rip),%rsp
/* Reset EFLAGS (subsumes CLI and CLD). */
- pushq $0
- popf
+ pushq $0
+ popf
+ /* Jump to high mappings. */
+ mov high_start(%rip),%rax
+ push %rax
+ ret
+__high_start:
+
lidt idt_descr(%rip)
cmp $(SECONDARY_CPU_FLAG),%ebx
add $8,%rdi
loop 1b
- xor %rax,%rax
mov 0x1001e0,%eax /* Multiboot info struct */
lea start(%rip),%rbx
sub $0x100000,%rbx
add %rbx,%rax
push %rax
- xor %rax,%rax
mov 0x1001e4,%eax /* Multiboot magic value */
push %rax
- /* Call into main C routine. This should never return.*/
- call cmain
- ud2 /* Force a panic (invalid opcode). */
+ call cmain
/* This is the default interrupt handler. */
int_msg:
1: jmp 1b
.code32
-
+
+ .org 0x1e0
+
/*** DESCRIPTOR TABLES ***/
.globl SYMBOL_NAME(idt)
.word 0
gdt_descr:
- .word (LAST_RESERVED_GDT_ENTRY*8)+7
+ .word (LAST_RESERVED_GDT_ENTRY*8)+7
SYMBOL_NAME(gdt):
.quad SYMBOL_NAME(gdt_table)
.word 0
idt_descr:
- .word 256*8-1
+ .word 256*8-1
SYMBOL_NAME(idt):
- .quad SYMBOL_NAME(idt_table)
+ .quad SYMBOL_NAME(idt_table)
ENTRY(stack_start)
- .quad SYMBOL_NAME(cpu0_stack) + 8100 - __PAGE_OFFSET
+ .quad SYMBOL_NAME(cpu0_stack) + 8100
high_start:
.quad __high_start
+/* Initial PML4 -- level-4 page table */
.org 0x1000
ENTRY(idle_pg_table)
ENTRY(idle_pg_table_4)
.quad 0x0000000000102007 # PML4[0]
.fill 261,8,0
.quad 0x0000000000102007 # PML4[262]
+
+/* Initial PDP -- level-3 page table */
.org 0x2000
ENTRY(idle_pg_table_l3)
.quad 0x0000000000103007
+
+/* Initial PDE -- level-2 page table. */
.org 0x3000
ENTRY(idle_pg_table_l2)
+ .macro identmap from=0, count=512
+ .if \count-1
+ identmap "(\from+0)","(\count/2)"
+ identmap "(\from+(0x200000*(\count/2)))","(\count/2)"
+ .else
+ .quad 0x00000000000001e3 + \from
+ .endif
+ .endm
+ identmap /* Too orangey for crows :-) */
+
.org 0x4000
ENTRY(cpu0_stack) # Initial stack is 8kB
+
.org 0x6000
ENTRY(stext)
ENTRY(_stext)
#ifndef __MULTIBOOT_H__
#define __MULTIBOOT_H__
-#ifndef __ELF__
-#error "Build on a 32-bit ELF system"
-#endif
-
/* The magic number passed by a Multiboot-compliant boot loader. */
-#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* The symbol table for a.out. */
-typedef struct
-{
- unsigned long tabsize;
- unsigned long strsize;
- unsigned long addr;
- unsigned long reserved;
+typedef struct {
+ u32 tabsize;
+ u32 strsize;
+ u32 addr;
+ u32 reserved;
} aout_symbol_table_t;
/* The section header table for ELF. */
-typedef struct
-{
- unsigned long num;
- unsigned long size;
- unsigned long addr;
- unsigned long shndx;
+typedef struct {
+ u32 num;
+ u32 size;
+ u32 addr;
+ u32 shndx;
} elf_section_header_table_t;
/* The Multiboot information. */
-typedef struct
-{
- unsigned long flags;
- unsigned long mem_lower;
- unsigned long mem_upper;
- unsigned long boot_device;
- unsigned long cmdline;
- unsigned long mods_count;
- unsigned long mods_addr;
- union
- {
- aout_symbol_table_t aout_sym;
- elf_section_header_table_t elf_sec;
- } u;
- unsigned long mmap_length;
- unsigned long mmap_addr;
+typedef struct {
+ u32 flags;
+ u32 mem_lower;
+ u32 mem_upper;
+ u32 boot_device;
+ u32 cmdline;
+ u32 mods_count;
+ u32 mods_addr;
+ union {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ u32 mmap_length;
+ u32 mmap_addr;
} multiboot_info_t;
/* The module structure. */
-typedef struct
-{
- unsigned long mod_start;
- unsigned long mod_end;
- unsigned long string;
- unsigned long reserved;
+typedef struct {
+ u32 mod_start;
+ u32 mod_end;
+ u32 string;
+ u32 reserved;
} module_t;
/* The memory map. Be careful that the offset 0 is base_addr_low
but no size. */
-typedef struct
-{
- unsigned long size;
- unsigned long base_addr_low;
- unsigned long base_addr_high;
- unsigned long length_low;
- unsigned long length_high;
- unsigned long type;
+typedef struct {
+ u32 size;
+ u32 base_addr_low;
+ u32 base_addr_high;
+ u32 length_low;
+ u32 length_high;
+ u32 type;
} memory_map_t;
#endif /* __MULTIBOOT_H__ */